home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ftp / RCS / ftp.c,v < prev    next >
Encoding:
Text File  |  1992-03-18  |  37.1 KB  |  1,977 lines

  1. head     1.4;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    shirriff:1.4; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.4
  10. date     92.03.17.23.27.16;  author shirriff;  state Exp;
  11. branches ;
  12. next     1.3;
  13.  
  14. 1.3
  15. date     90.10.27.13.48.39;  author shirriff;  state Exp;
  16. branches ;
  17. next     1.2;
  18.  
  19. 1.2
  20. date     88.07.21.09.56.38;  author ouster;  state Exp;
  21. branches ;
  22. next     1.1;
  23.  
  24. 1.1
  25. date     88.07.21.09.46.51;  author ouster;  state Exp;
  26. branches ;
  27. next     ;
  28.  
  29.  
  30. desc
  31. @@
  32.  
  33.  
  34. 1.4
  35. log
  36. @Changes to use varargs.
  37. @
  38. text
  39. @/*
  40.  * Copyright (c) 1985, 1989 Regents of the University of California.
  41.  * All rights reserved.
  42.  *
  43.  * Redistribution and use in source and binary forms are permitted
  44.  * provided that the above copyright notice and this paragraph are
  45.  * duplicated in all such forms and that any documentation,
  46.  * advertising materials, and other materials related to such
  47.  * distribution and use acknowledge that the software was developed
  48.  * by the University of California, Berkeley.  The name of the
  49.  * University may not be used to endorse or promote products derived
  50.  * from this software without specific prior written permission.
  51.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  52.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  53.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  54.  */
  55.  
  56. #ifndef lint
  57. static char sccsid[] = "@@(#)ftp.c    5.26 (Berkeley) 3/21/89";
  58. #endif /* not lint */
  59.  
  60. #include <sys/param.h>
  61. #include <sys/stat.h>
  62. #include <sys/ioctl.h>
  63. #include <sys/socket.h>
  64. #include <sys/time.h>
  65. #include <sys/file.h>
  66.  
  67. #include <netinet/in.h>
  68. #include <arpa/ftp.h>
  69. #include <arpa/telnet.h>
  70.  
  71. #include <stdio.h>
  72. #include <signal.h>
  73. #include <errno.h>
  74. #include <netdb.h>
  75. #include <fcntl.h>
  76. #include <pwd.h>
  77. #include <varargs.h>
  78.  
  79. #include "ftp_var.h"
  80.  
  81. struct    sockaddr_in hisctladdr;
  82. struct    sockaddr_in data_addr;
  83. int    data = -1;
  84. int    abrtflag = 0;
  85. int    ptflag = 0;
  86. int    connected;
  87. struct    sockaddr_in myctladdr;
  88. uid_t    getuid();
  89. off_t    restart_point = 0;
  90.  
  91. FILE    *cin, *cout;
  92. FILE    *dataconn();
  93.  
  94. char *
  95. hookup(host, port)
  96.     char *host;
  97.     int port;
  98. {
  99.     register struct hostent *hp = 0;
  100.     int s,len;
  101.     static char hostnamebuf[80];
  102.  
  103.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  104.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  105.     if (hisctladdr.sin_addr.s_addr != -1) {
  106.         hisctladdr.sin_family = AF_INET;
  107.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  108.     } else {
  109.         hp = gethostbyname(host);
  110.         if (hp == NULL) {
  111.             fprintf(stderr, "ftp: %s: ", host);
  112.             herror((char *)NULL);
  113.             code = -1;
  114.             return((char *) 0);
  115.         }
  116.         hisctladdr.sin_family = hp->h_addrtype;
  117.         bcopy(hp->h_addr_list[0],
  118.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  119.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  120.     }
  121.     hostname = hostnamebuf;
  122.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  123.     if (s < 0) {
  124.         perror("ftp: socket");
  125.         code = -1;
  126.         return (0);
  127.     }
  128.     hisctladdr.sin_port = port;
  129.     while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
  130.         if (hp && hp->h_addr_list[1]) {
  131.             int oerrno = errno;
  132.  
  133.             fprintf(stderr, "ftp: connect to address %s: ",
  134.                 inet_ntoa(hisctladdr.sin_addr));
  135.             errno = oerrno;
  136.             perror((char *) 0);
  137.             hp->h_addr_list++;
  138.             bcopy(hp->h_addr_list[0],
  139.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  140.             fprintf(stdout, "Trying %s...\n",
  141.                 inet_ntoa(hisctladdr.sin_addr));
  142.             (void) close(s);
  143.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  144.             if (s < 0) {
  145.                 perror("ftp: socket");
  146.                 code = -1;
  147.                 return (0);
  148.             }
  149.             continue;
  150.         }
  151.         perror("ftp: connect");
  152.         code = -1;
  153.         goto bad;
  154.     }
  155.     len = sizeof (myctladdr);
  156.     if (getsockname(s, (char *)&myctladdr, &len) < 0) {
  157.         perror("ftp: getsockname");
  158.         code = -1;
  159.         goto bad;
  160.     }
  161.     cin = fdopen(s, "r");
  162.     cout = fdopen(s, "w");
  163.     if (cin == NULL || cout == NULL) {
  164.         fprintf(stderr, "ftp: fdopen failed.\n");
  165.         if (cin)
  166.             (void) fclose(cin);
  167.         if (cout)
  168.             (void) fclose(cout);
  169.         code = -1;
  170.         goto bad;
  171.     }
  172.     if (verbose)
  173.         printf("Connected to %s.\n", hostname);
  174.     if (getreply(0) > 2) {     /* read startup message from server */
  175.         if (cin)
  176.             (void) fclose(cin);
  177.         if (cout)
  178.             (void) fclose(cout);
  179.         code = -1;
  180.         goto bad;
  181.     }
  182. #ifdef SO_OOBINLINE
  183.     {
  184.     int on = 1;
  185.  
  186.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
  187.         < 0 && debug) {
  188.             perror("ftp: setsockopt");
  189.         }
  190.     }
  191. #endif SO_OOBINLINE
  192.  
  193.     return (hostname);
  194. bad:
  195.     (void) close(s);
  196.     return ((char *)0);
  197. }
  198.  
  199. login(host)
  200.     char *host;
  201. {
  202.     char tmp[80];
  203.     char *user, *pass, *acct, *getlogin(), *getpass();
  204.     int n, aflag = 0;
  205.  
  206.     user = pass = acct = 0;
  207.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  208.         code = -1;
  209.         return(0);
  210.     }
  211.     if (user == NULL) {
  212.         char *myname = getlogin();
  213.  
  214.         if (myname == NULL) {
  215.             struct passwd *pp = getpwuid(getuid());
  216.  
  217.             if (pp != NULL)
  218.                 myname = pp->pw_name;
  219.         }
  220.         printf("Name (%s:%s): ", host, myname);
  221.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  222.         tmp[strlen(tmp) - 1] = '\0';
  223.         if (*tmp == '\0')
  224.             user = myname;
  225.         else
  226.             user = tmp;
  227.     }
  228.     n = command("USER %s", user);
  229.     if (n == CONTINUE) {
  230.         if (pass == NULL)
  231.             pass = getpass("Password:");
  232.         n = command("PASS %s", pass);
  233.     }
  234.     if (n == CONTINUE) {
  235.         aflag++;
  236.         acct = getpass("Account:");
  237.         n = command("ACCT %s", acct);
  238.     }
  239.     if (n != COMPLETE) {
  240.         fprintf(stderr, "Login failed.\n");
  241.         return (0);
  242.     }
  243.     if (!aflag && acct != NULL)
  244.         (void) command("ACCT %s", acct);
  245.     if (proxy)
  246.         return(1);
  247.     for (n = 0; n < macnum; ++n) {
  248.         if (!strcmp("init", macros[n].mac_name)) {
  249.             (void) strcpy(line, "$init");
  250.             makeargv();
  251.             domacro(margc, margv);
  252.             break;
  253.         }
  254.     }
  255.     return (1);
  256. }
  257.  
  258. cmdabort()
  259. {
  260.     extern jmp_buf ptabort;
  261.  
  262.     printf("\n");
  263.     (void) fflush(stdout);
  264.     abrtflag++;
  265.     if (ptflag)
  266.         longjmp(ptabort,1);
  267. }
  268.  
  269. /*VARARGS1*/
  270. command(va_alist)
  271.     va_dcl    /* Format string followed by zero or more arguments. */
  272. {
  273.     char *fmt;
  274.     va_list args;
  275.     int r, (*oldintr)(), cmdabort();
  276.  
  277.     va_start(args);
  278.     fmt = va_arg(args, char *);
  279.  
  280.     abrtflag = 0;
  281.     if (debug) {
  282.         printf("---> ");
  283.         (void) vfprintf(stdout, fmt, args);
  284.         printf("\n");
  285.         (void) fflush(stdout);
  286.     }
  287.     if (cout == NULL) {
  288.         perror ("No control connection for command");
  289.         code = -1;
  290.         return (0);
  291.     }
  292.     oldintr = signal(SIGINT,cmdabort);
  293.     (void) vfprintf(cout, fmt, args);
  294.     fprintf(cout, "\r\n");
  295.     (void) fflush(cout);
  296.     cpend = 1;
  297.     r = getreply(!strcmp(fmt, "QUIT"));
  298.     if (abrtflag && oldintr != SIG_IGN)
  299.         (*oldintr)();
  300.     (void) signal(SIGINT, oldintr);
  301.     return(r);
  302. }
  303.  
  304. char reply_string[BUFSIZ];
  305.  
  306. #include <ctype.h>
  307.  
  308. getreply(expecteof)
  309.     int expecteof;
  310. {
  311.     register int c, n;
  312.     register int dig;
  313.     register char *cp;
  314.     int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
  315.     int pflag = 0;
  316.     char *pt = pasv;
  317.  
  318.     cp = reply_string;
  319.     oldintr = signal(SIGINT,cmdabort);
  320.     for (;;) {
  321.         dig = n = code = 0;
  322.         while ((c = getc(cin)) != '\n') {
  323.             if (c == IAC) {     /* handle telnet commands */
  324.                 switch (c = getc(cin)) {
  325.                 case WILL:
  326.                 case WONT:
  327.                     c = getc(cin);
  328.                     fprintf(cout, "%c%c%c",IAC,DONT,c);
  329.                     (void) fflush(cout);
  330.                     break;
  331.                 case DO:
  332.                 case DONT:
  333.                     c = getc(cin);
  334.                     fprintf(cout, "%c%c%c",IAC,WONT,c);
  335.                     (void) fflush(cout);
  336.                     break;
  337.                 default:
  338.                     break;
  339.                 }
  340.                 continue;
  341.             }
  342.             dig++;
  343.             if (c == EOF) {
  344.                 if (expecteof) {
  345.                     (void) signal(SIGINT,oldintr);
  346.                     code = 221;
  347.                     return (0);
  348.                 }
  349.                 lostpeer();
  350.                 if (verbose) {
  351.                     printf("421 Service not available, remote server has closed connection\n");
  352.                     (void) fflush(stdout);
  353.                 }
  354.                 code = 421;
  355.                 return(4);
  356.             }
  357.             if (c != '\r' && (verbose > 0 ||
  358.                 (verbose > -1 && n == '5' && dig > 4))) {
  359.                 if (proxflag &&
  360.                    (dig == 1 || dig == 5 && verbose == 0))
  361.                     printf("%s:",hostname);
  362.                 (void) putchar(c);
  363.             }
  364.             if (dig < 4 && isdigit(c))
  365.                 code = code * 10 + (c - '0');
  366.             if (!pflag && code == 227)
  367.                 pflag = 1;
  368.             if (dig > 4 && pflag == 1 && isdigit(c))
  369.                 pflag = 2;
  370.             if (pflag == 2) {
  371.                 if (c != '\r' && c != ')')
  372.                     *pt++ = c;
  373.                 else {
  374.                     *pt = '\0';
  375.                     pflag = 3;
  376.                 }
  377.             }
  378.             if (dig == 4 && c == '-') {
  379.                 if (continuation)
  380.                     code = 0;
  381.                 continuation++;
  382.             }
  383.             if (n == 0)
  384.                 n = c;
  385.             *cp++ = c;
  386.         }
  387.         if (verbose > 0 || verbose > -1 && n == '5') {
  388.             (void) putchar(c);
  389.             (void) fflush (stdout);
  390.         }
  391.         if (continuation && code != originalcode) {
  392.             if (originalcode == 0)
  393.                 originalcode = code;
  394.             continue;
  395.         }
  396.         *cp = '\0';
  397.         if (n != '1')
  398.             cpend = 0;
  399.         (void) signal(SIGINT,oldintr);
  400.         if (code == 421 || originalcode == 421)
  401.             lostpeer();
  402.         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  403.             (*oldintr)();
  404.         return (n - '0');
  405.     }
  406. }
  407.  
  408. empty(mask, sec)
  409.     struct fd_set *mask;
  410.     int sec;
  411. {
  412.     struct timeval t;
  413.  
  414.     t.tv_sec = (long) sec;
  415.     t.tv_usec = 0;
  416.     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  417. }
  418.  
  419. jmp_buf    sendabort;
  420.  
  421. abortsend()
  422. {
  423.  
  424.     mflag = 0;
  425.     abrtflag = 0;
  426.     printf("\nsend aborted\n");
  427.     (void) fflush(stdout);
  428.     longjmp(sendabort, 1);
  429. }
  430.  
  431. #define HASHBYTES 1024
  432.  
  433. sendrequest(cmd, local, remote, printnames)
  434.     char *cmd, *local, *remote;
  435.     int printnames;
  436. {
  437.     FILE *fin, *dout = 0, *popen();
  438.     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
  439.     int abortsend();
  440.     char buf[BUFSIZ], *bufp;
  441.     long bytes = 0, hashbytes = HASHBYTES;
  442.     register int c, d;
  443.     struct stat st;
  444.     struct timeval start, stop;
  445.     char *mode;
  446.  
  447.     if (verbose && printnames) {
  448.         if (local && *local != '-')
  449.             printf("local: %s ", local);
  450.         if (remote)
  451.             printf("remote: %s\n", remote);
  452.     }
  453.     if (proxy) {
  454.         proxtrans(cmd, local, remote);
  455.         return;
  456.     }
  457.     closefunc = NULL;
  458.     oldintr = NULL;
  459.     oldintp = NULL;
  460.     mode = "w";
  461.     if (setjmp(sendabort)) {
  462.         while (cpend) {
  463.             (void) getreply(0);
  464.         }
  465.         if (data >= 0) {
  466.             (void) close(data);
  467.             data = -1;
  468.         }
  469.         if (oldintr)
  470.             (void) signal(SIGINT,oldintr);
  471.         if (oldintp)
  472.             (void) signal(SIGPIPE,oldintp);
  473.         code = -1;
  474.         return;
  475.     }
  476.     oldintr = signal(SIGINT, abortsend);
  477.     if (strcmp(local, "-") == 0)
  478.         fin = stdin;
  479.     else if (*local == '|') {
  480.         oldintp = signal(SIGPIPE,SIG_IGN);
  481.         fin = popen(local + 1, "r");
  482.         if (fin == NULL) {
  483.             perror(local + 1);
  484.             (void) signal(SIGINT, oldintr);
  485.             (void) signal(SIGPIPE, oldintp);
  486.             code = -1;
  487.             return;
  488.         }
  489.         closefunc = pclose;
  490.     } else {
  491.         fin = fopen(local, "r");
  492.         if (fin == NULL) {
  493.             perror(local);
  494.             (void) signal(SIGINT, oldintr);
  495.             code = -1;
  496.             return;
  497.         }
  498.         closefunc = fclose;
  499.         if (fstat(fileno(fin), &st) < 0 ||
  500.             (st.st_mode&S_IFMT) != S_IFREG) {
  501.             fprintf(stdout, "%s: not a plain file.\n", local);
  502.             (void) signal(SIGINT, oldintr);
  503.             fclose(fin);
  504.             code = -1;
  505.             return;
  506.         }
  507.     }
  508.     if (initconn()) {
  509.         (void) signal(SIGINT, oldintr);
  510.         if (oldintp)
  511.             (void) signal(SIGPIPE, oldintp);
  512.         code = -1;
  513.         if (closefunc != NULL)
  514.             (*closefunc)(fin);
  515.         return;
  516.     }
  517.     if (setjmp(sendabort))
  518.         goto abort;
  519.  
  520.     if (restart_point &&
  521.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  522.         if (fseek(fin, (long) restart_point, 0) < 0) {
  523.             perror(local);
  524.             restart_point = 0;
  525.             if (closefunc != NULL)
  526.                 (*closefunc)(fin);
  527.             return;
  528.         }
  529.         if (command("REST %ld", (long) restart_point)
  530.             != CONTINUE) {
  531.             restart_point = 0;
  532.             if (closefunc != NULL)
  533.                 (*closefunc)(fin);
  534.             return;
  535.         }
  536.         restart_point = 0;
  537.         mode = "r+w";
  538.     }
  539.     if (remote) {
  540.         if (command("%s %s", cmd, remote) != PRELIM) {
  541.             (void) signal(SIGINT, oldintr);
  542.             if (oldintp)
  543.                 (void) signal(SIGPIPE, oldintp);
  544.             if (closefunc != NULL)
  545.                 (*closefunc)(fin);
  546.             return;
  547.         }
  548.     } else
  549.         if (command("%s", cmd) != PRELIM) {
  550.             (void) signal(SIGINT, oldintr);
  551.             if (oldintp)
  552.                 (void) signal(SIGPIPE, oldintp);
  553.             if (closefunc != NULL)
  554.                 (*closefunc)(fin);
  555.             return;
  556.         }
  557.     dout = dataconn(mode);
  558.     if (dout == NULL)
  559.         goto abort;
  560.     (void) gettimeofday(&start, (struct timezone *)0);
  561.     oldintp = signal(SIGPIPE, SIG_IGN);
  562.     switch (type) {
  563.  
  564.     case TYPE_I:
  565.     case TYPE_L:
  566.         errno = d = 0;
  567.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  568.             bytes += c;
  569.             for (bufp = buf; c > 0; c -= d, bufp += d)
  570.                 if ((d = write(fileno(dout), bufp, c)) <= 0)
  571.                     break;
  572.             if (hash) {
  573.                 while (bytes >= hashbytes) {
  574.                     (void) putchar('#');
  575.                     hashbytes += HASHBYTES;
  576.                 }
  577.                 (void) fflush(stdout);
  578.             }
  579.         }
  580.         if (hash && bytes > 0) {
  581.             if (bytes < HASHBYTES)
  582.                 (void) putchar('#');
  583.             (void) putchar('\n');
  584.             (void) fflush(stdout);
  585.         }
  586.         if (c < 0)
  587.             perror(local);
  588.         if (d <= 0) {
  589.             if (d == 0)
  590.                 fprintf(stderr, "netout: write returned 0?\n");
  591.             else if (errno != EPIPE) 
  592.                 perror("netout");
  593.             bytes = -1;
  594.         }
  595.         break;
  596.  
  597.     case TYPE_A:
  598.         while ((c = getc(fin)) != EOF) {
  599.             if (c == '\n') {
  600.                 while (hash && (bytes >= hashbytes)) {
  601.                     (void) putchar('#');
  602.                     (void) fflush(stdout);
  603.                     hashbytes += HASHBYTES;
  604.                 }
  605.                 if (ferror(dout))
  606.                     break;
  607.                 (void) putc('\r', dout);
  608.                 bytes++;
  609.             }
  610.             (void) putc(c, dout);
  611.             bytes++;
  612.     /*        if (c == '\r') {                  */
  613.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  614.     /*            bytes++;                */
  615.     /*        }                                      */    
  616.         }
  617.         if (hash) {
  618.             if (bytes < hashbytes)
  619.                 (void) putchar('#');
  620.             (void) putchar('\n');
  621.             (void) fflush(stdout);
  622.         }
  623.         if (ferror(fin))
  624.             perror(local);
  625.         if (ferror(dout)) {
  626.             if (errno != EPIPE)
  627.                 perror("netout");
  628.             bytes = -1;
  629.         }
  630.         break;
  631.     }
  632.     (void) gettimeofday(&stop, (struct timezone *)0);
  633.     if (closefunc != NULL)
  634.         (*closefunc)(fin);
  635.     (void) fclose(dout);
  636.     (void) getreply(0);
  637.     (void) signal(SIGINT, oldintr);
  638.     if (oldintp)
  639.         (void) signal(SIGPIPE, oldintp);
  640.     if (bytes > 0)
  641.         ptransfer("sent", bytes, &start, &stop);
  642.     return;
  643. abort:
  644.     (void) gettimeofday(&stop, (struct timezone *)0);
  645.     (void) signal(SIGINT, oldintr);
  646.     if (oldintp)
  647.         (void) signal(SIGPIPE, oldintp);
  648.     if (!cpend) {
  649.         code = -1;
  650.         return;
  651.     }
  652.     if (data >= 0) {
  653.         (void) close(data);
  654.         data = -1;
  655.     }
  656.     if (dout)
  657.         (void) fclose(dout);
  658.     (void) getreply(0);
  659.     code = -1;
  660.     if (closefunc != NULL && fin != NULL)
  661.         (*closefunc)(fin);
  662.     if (bytes > 0)
  663.         ptransfer("sent", bytes, &start, &stop);
  664. }
  665.  
  666. jmp_buf    recvabort;
  667.  
  668. abortrecv()
  669. {
  670.  
  671.     mflag = 0;
  672.     abrtflag = 0;
  673.     printf("\n");
  674.     (void) fflush(stdout);
  675.     longjmp(recvabort, 1);
  676. }
  677.  
  678. recvrequest(cmd, local, remote, mode, printnames)
  679.     char *cmd, *local, *remote, *mode;
  680. {
  681.     FILE *fout, *din = 0, *popen();
  682.     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 
  683.     int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
  684.     char *bufp, *gunique(), msg;
  685.     static char *buf;
  686.     static int bufsize;
  687.     long bytes = 0, hashbytes = HASHBYTES;
  688.     struct fd_set mask;
  689.     register int c, d;
  690.     struct timeval start, stop;
  691.     struct stat st;
  692.     extern char *malloc();
  693.  
  694.     is_retr = strcmp(cmd, "RETR") == 0;
  695.     if (is_retr && verbose && printnames) {
  696.         if (local && *local != '-')
  697.             printf("local: %s ", local);
  698.         if (remote)
  699.             printf("remote: %s\n", remote);
  700.     }
  701.     if (proxy && is_retr) {
  702.         proxtrans(cmd, local, remote);
  703.         return;
  704.     }
  705.     closefunc = NULL;
  706.     oldintr = NULL;
  707.     oldintp = NULL;
  708.     tcrflag = !crflag && is_retr;
  709.     if (setjmp(recvabort)) {
  710.         while (cpend) {
  711.             (void) getreply(0);
  712.         }
  713.         if (data >= 0) {
  714.             (void) close(data);
  715.             data = -1;
  716.         }
  717.         if (oldintr)
  718.             (void) signal(SIGINT, oldintr);
  719.         code = -1;
  720.         return;
  721.     }
  722.     oldintr = signal(SIGINT, abortrecv);
  723.     if (strcmp(local, "-") && *local != '|') {
  724.         if (access(local, 2) < 0) {
  725.             char *dir = rindex(local, '/');
  726.  
  727.             if (errno != ENOENT && errno != EACCES) {
  728.                 perror(local);
  729.                 (void) signal(SIGINT, oldintr);
  730.                 code = -1;
  731.                 return;
  732.             }
  733.             if (dir != NULL)
  734.                 *dir = 0;
  735.             d = access(dir ? local : ".", 2);
  736.             if (dir != NULL)
  737.                 *dir = '/';
  738.             if (d < 0) {
  739.                 perror(local);
  740.                 (void) signal(SIGINT, oldintr);
  741.                 code = -1;
  742.                 return;
  743.             }
  744.             if (!runique && errno == EACCES &&
  745.                 chmod(local, 0600) < 0) {
  746.                 perror(local);
  747.                 (void) signal(SIGINT, oldintr);
  748.                 code = -1;
  749.                 return;
  750.             }
  751.             if (runique && errno == EACCES &&
  752.                (local = gunique(local)) == NULL) {
  753.                 (void) signal(SIGINT, oldintr);
  754.                 code = -1;
  755.                 return;
  756.             }
  757.         }
  758.         else if (runique && (local = gunique(local)) == NULL) {
  759.             (void) signal(SIGINT, oldintr);
  760.             code = -1;
  761.             return;
  762.         }
  763.     }
  764.     if (initconn()) {
  765.         (void) signal(SIGINT, oldintr);
  766.         code = -1;
  767.         return;
  768.     }
  769.     if (setjmp(recvabort))
  770.         goto abort;
  771.     if (!is_retr) {
  772.         if (type != TYPE_A) {
  773.             oldtype = type;
  774.             oldverbose = verbose;
  775.             if (!debug)
  776.                 verbose = 0;
  777.             setascii();
  778.             verbose = oldverbose;
  779.         }
  780.     } else if (restart_point) {
  781.         if (command("REST %ld", (long) restart_point) != CONTINUE)
  782.             return;
  783.     }
  784.     if (remote) {
  785.         if (command("%s %s", cmd, remote) != PRELIM) {
  786.             (void) signal(SIGINT, oldintr);
  787.             if (oldtype) {
  788.                 if (!debug)
  789.                     verbose = 0;
  790.                 switch (oldtype) {
  791.                     case TYPE_I:
  792.                         setbinary();
  793.                         break;
  794.                     case TYPE_E:
  795.                         setebcdic();
  796.                         break;
  797.                     case TYPE_L:
  798.                         settenex();
  799.                         break;
  800.                 }
  801.                 verbose = oldverbose;
  802.             }
  803.             return;
  804.         }
  805.     } else {
  806.         if (command("%s", cmd) != PRELIM) {
  807.             (void) signal(SIGINT, oldintr);
  808.             if (oldtype) {
  809.                 if (!debug)
  810.                     verbose = 0;
  811.                 switch (oldtype) {
  812.                     case TYPE_I:
  813.                         setbinary();
  814.                         break;
  815.                     case TYPE_E:
  816.                         setebcdic();
  817.                         break;
  818.                     case TYPE_L:
  819.                         settenex();
  820.                         break;
  821.                 }
  822.                 verbose = oldverbose;
  823.             }
  824.             return;
  825.         }
  826.     }
  827.     din = dataconn("r");
  828.     if (din == NULL)
  829.         goto abort;
  830.     if (strcmp(local, "-") == 0)
  831.         fout = stdout;
  832.     else if (*local == '|') {
  833.         oldintp = signal(SIGPIPE, SIG_IGN);
  834.         fout = popen(local + 1, "w");
  835.         if (fout == NULL) {
  836.             perror(local+1);
  837.             goto abort;
  838.         }
  839.         closefunc = pclose;
  840.     } else {
  841.         fout = fopen(local, mode);
  842.         if (fout == NULL) {
  843.             perror(local);
  844.             goto abort;
  845.         }
  846.         closefunc = fclose;
  847.     }
  848.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  849.         st.st_blksize = BUFSIZ;
  850.     if (st.st_blksize > bufsize) {
  851.         if (buf)
  852.             (void) free(buf);
  853.         buf = malloc(st.st_blksize);
  854.         if (buf == NULL) {
  855.             perror("malloc");
  856.             bufsize = 0;
  857.             goto abort;
  858.         }
  859.         bufsize = st.st_blksize;
  860.     }
  861.     (void) gettimeofday(&start, (struct timezone *)0);
  862.     switch (type) {
  863.  
  864.     case TYPE_I:
  865.     case TYPE_L:
  866.         if (restart_point &&
  867.             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
  868.             perror(local);
  869.             if (closefunc != NULL)
  870.                 (*closefunc)(fout);
  871.             return;
  872.         }
  873.         errno = d = 0;
  874.         while ((c = read(fileno(din), buf, bufsize)) > 0) {
  875.             if ((d = write(fileno(fout), buf, c)) != c)
  876.                 break;
  877.             bytes += c;
  878.             if (hash) {
  879.                 while (bytes >= hashbytes) {
  880.                     (void) putchar('#');
  881.                     hashbytes += HASHBYTES;
  882.                 }
  883.                 (void) fflush(stdout);
  884.             }
  885.         }
  886.         if (hash && bytes > 0) {
  887.             if (bytes < HASHBYTES)
  888.                 (void) putchar('#');
  889.             (void) putchar('\n');
  890.             (void) fflush(stdout);
  891.         }
  892.         if (c < 0) {
  893.             if (errno != EPIPE)
  894.                 perror("netin");
  895.             bytes = -1;
  896.         }
  897.         if (d < c) {
  898.             if (d < 0)
  899.                 perror(local);
  900.             else
  901.                 fprintf(stderr, "%s: short write\n", local);
  902.         }
  903.         break;
  904.  
  905.     case TYPE_A:
  906.         if (restart_point) {
  907.             register int i, n, c;
  908.  
  909.             if (fseek(fout, 0L, L_SET) < 0)
  910.                 goto done;
  911.             n = restart_point;
  912.             i = 0;
  913.             while (i++ < n) {
  914.                 if ((c=getc(fout)) == EOF)
  915.                     goto done;
  916.                 if (c == '\n')
  917.                     i++;
  918.             }
  919.             if (fseek(fout, 0L, L_INCR) < 0) {
  920. done:
  921.                 perror(local);
  922.                 if (closefunc != NULL)
  923.                     (*closefunc)(fout);
  924.                 return;
  925.             }
  926.         }
  927.         while ((c = getc(din)) != EOF) {
  928.             while (c == '\r') {
  929.                 while (hash && (bytes >= hashbytes)) {
  930.                     (void) putchar('#');
  931.                     (void) fflush(stdout);
  932.                     hashbytes += HASHBYTES;
  933.                 }
  934.                 bytes++;
  935.                 if ((c = getc(din)) != '\n' || tcrflag) {
  936.                     if (ferror(fout))
  937.                         goto break2;
  938.                     (void) putc('\r', fout);
  939.                     if (c == '\0') {
  940.                         bytes++;
  941.                         goto contin2;
  942.                     }
  943.                     if (c == EOF)
  944.                         goto contin2;
  945.                 }
  946.             }
  947.             (void) putc(c, fout);
  948.             bytes++;
  949.     contin2:    ;
  950.         }
  951. break2:
  952.         if (hash) {
  953.             if (bytes < hashbytes)
  954.                 (void) putchar('#');
  955.             (void) putchar('\n');
  956.             (void) fflush(stdout);
  957.         }
  958.         if (ferror(din)) {
  959.             if (errno != EPIPE)
  960.                 perror("netin");
  961.             bytes = -1;
  962.         }
  963.         if (ferror(fout))
  964.             perror(local);
  965.         break;
  966.     }
  967.     if (closefunc != NULL)
  968.         (*closefunc)(fout);
  969.     (void) signal(SIGINT, oldintr);
  970.     if (oldintp)
  971.         (void) signal(SIGPIPE, oldintp);
  972.     (void) gettimeofday(&stop, (struct timezone *)0);
  973.     (void) fclose(din);
  974.     (void) getreply(0);
  975.     if (bytes > 0 && is_retr)
  976.         ptransfer("received", bytes, &start, &stop);
  977.     if (oldtype) {
  978.         if (!debug)
  979.             verbose = 0;
  980.         switch (oldtype) {
  981.             case TYPE_I:
  982.                 setbinary();
  983.                 break;
  984.             case TYPE_E:
  985.                 setebcdic();
  986.                 break;
  987.             case TYPE_L:
  988.                 settenex();
  989.                 break;
  990.         }
  991.         verbose = oldverbose;
  992.     }
  993.     return;
  994. abort:
  995.  
  996. /* abort using RFC959 recommended IP,SYNC sequence  */
  997.  
  998.     (void) gettimeofday(&stop, (struct timezone *)0);
  999.     if (oldintp)
  1000.         (void) signal(SIGPIPE, oldintr);
  1001.     (void) signal(SIGINT,SIG_IGN);
  1002.     if (oldtype) {
  1003.         if (!debug)
  1004.             verbose = 0;
  1005.         switch (oldtype) {
  1006.             case TYPE_I:
  1007.                 setbinary();
  1008.                 break;
  1009.             case TYPE_E:
  1010.                 setebcdic();
  1011.                 break;
  1012.             case TYPE_L:
  1013.                 settenex();
  1014.                 break;
  1015.         }
  1016.         verbose = oldverbose;
  1017.     }
  1018.     if (!cpend) {
  1019.         code = -1;
  1020.         (void) signal(SIGINT,oldintr);
  1021.         return;
  1022.     }
  1023.  
  1024.     fprintf(cout,"%c%c",IAC,IP);
  1025.     (void) fflush(cout); 
  1026.     msg = IAC;
  1027. /* send IAC in urgent mode instead of DM because UNIX places oob mark */
  1028. /* after urgent byte rather than before as now is protocol            */
  1029.     if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
  1030.         perror("abort");
  1031.     }
  1032.     fprintf(cout,"%cABOR\r\n",DM);
  1033.     (void) fflush(cout);
  1034.     FD_ZERO(&mask);
  1035.     FD_SET(fileno(cin), &mask);
  1036.     if (din) { 
  1037.         FD_SET(fileno(din), &mask);
  1038.     }
  1039.     if ((nfnd = empty(&mask,10)) <= 0) {
  1040.         if (nfnd < 0) {
  1041.             perror("abort");
  1042.         }
  1043.         code = -1;
  1044.         lostpeer();
  1045.     }
  1046.     if (din && FD_ISSET(fileno(din), &mask)) {
  1047.         while ((c = read(fileno(din), buf, bufsize)) > 0)
  1048.             ;
  1049.     }
  1050.     if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
  1051.         if (data >= 0) {
  1052.             (void) close(data);
  1053.             data = -1;
  1054.         }
  1055.         (void) getreply(0);
  1056.     }
  1057.     (void) getreply(0);
  1058.     code = -1;
  1059.     if (data >= 0) {
  1060.         (void) close(data);
  1061.         data = -1;
  1062.     }
  1063.     if (closefunc != NULL && fout != NULL)
  1064.         (*closefunc)(fout);
  1065.     if (din)
  1066.         (void) fclose(din);
  1067.     if (bytes > 0)
  1068.         ptransfer("received", bytes, &start, &stop);
  1069.     (void) signal(SIGINT,oldintr);
  1070. }
  1071.  
  1072. /*
  1073.  * Need to start a listen on the data channel
  1074.  * before we send the command, otherwise the
  1075.  * server's connect may fail.
  1076.  */
  1077. int sendport = -1;
  1078.  
  1079. initconn()
  1080. {
  1081.     register char *p, *a;
  1082.     int result, len, tmpno = 0;
  1083.     int on = 1;
  1084.  
  1085. noport:
  1086.     data_addr = myctladdr;
  1087.     if (sendport)
  1088.         data_addr.sin_port = 0;    /* let system pick one */ 
  1089.     if (data != -1)
  1090.         (void) close (data);
  1091.     data = socket(AF_INET, SOCK_STREAM, 0);
  1092.     if (data < 0) {
  1093.         perror("ftp: socket");
  1094.         if (tmpno)
  1095.             sendport = 1;
  1096.         return (1);
  1097.     }
  1098.     if (!sendport)
  1099.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1100.             perror("ftp: setsockopt (reuse address)");
  1101.             goto bad;
  1102.         }
  1103.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1104.         perror("ftp: bind");
  1105.         goto bad;
  1106.     }
  1107.     if (options & SO_DEBUG &&
  1108.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1109.         perror("ftp: setsockopt (ignored)");
  1110.     len = sizeof (data_addr);
  1111.     if (getsockname(data, (char *)&data_addr, &len) < 0) {
  1112.         perror("ftp: getsockname");
  1113.         goto bad;
  1114.     }
  1115.     if (listen(data, 1) < 0)
  1116.         perror("ftp: listen");
  1117.     if (sendport) {
  1118.         a = (char *)&data_addr.sin_addr;
  1119.         p = (char *)&data_addr.sin_port;
  1120. #define    UC(b)    (((int)b)&0xff)
  1121.         result =
  1122.             command("PORT %d,%d,%d,%d,%d,%d",
  1123.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1124.               UC(p[0]), UC(p[1]));
  1125.         if (result == ERROR && sendport == -1) {
  1126.             sendport = 0;
  1127.             tmpno = 1;
  1128.             goto noport;
  1129.         }
  1130.         return (result != COMPLETE);
  1131.     }
  1132.     if (tmpno)
  1133.         sendport = 1;
  1134.     return (0);
  1135. bad:
  1136.     (void) close(data), data = -1;
  1137.     if (tmpno)
  1138.         sendport = 1;
  1139.     return (1);
  1140. }
  1141.  
  1142. FILE *
  1143. dataconn(mode)
  1144.     char *mode;
  1145. {
  1146.     struct sockaddr_in from;
  1147.     int s, fromlen = sizeof (from);
  1148.  
  1149.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1150.     if (s < 0) {
  1151.         perror("ftp: accept");
  1152.         (void) close(data), data = -1;
  1153.         return (NULL);
  1154.     }
  1155.     (void) close(data);
  1156.     data = s;
  1157.     return (fdopen(data, mode));
  1158. }
  1159.  
  1160. ptransfer(direction, bytes, t0, t1)
  1161.     char *direction;
  1162.     long bytes;
  1163.     struct timeval *t0, *t1;
  1164. {
  1165.     struct timeval td;
  1166.     float s, bs;
  1167.  
  1168.     if (verbose) {
  1169.         tvsub(&td, t1, t0);
  1170.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1171. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1172.         bs = bytes / nz(s);
  1173.         printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
  1174.             bytes, direction, s, bs / 1024.);
  1175.     }
  1176. }
  1177.  
  1178. /*tvadd(tsum, t0)
  1179.     struct timeval *tsum, *t0;
  1180. {
  1181.  
  1182.     tsum->tv_sec += t0->tv_sec;
  1183.     tsum->tv_usec += t0->tv_usec;
  1184.     if (tsum->tv_usec > 1000000)
  1185.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1186. } */
  1187.  
  1188. tvsub(tdiff, t1, t0)
  1189.     struct timeval *tdiff, *t1, *t0;
  1190. {
  1191.  
  1192.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1193.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1194.     if (tdiff->tv_usec < 0)
  1195.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1196. }
  1197.  
  1198. psabort()
  1199. {
  1200.     extern int abrtflag;
  1201.  
  1202.     abrtflag++;
  1203. }
  1204.  
  1205. pswitch(flag)
  1206.     int flag;
  1207. {
  1208.     extern int proxy, abrtflag;
  1209.     int (*oldintr)();
  1210.     static struct comvars {
  1211.         int connect;
  1212.         char name[MAXHOSTNAMELEN];
  1213.         struct sockaddr_in mctl;
  1214.         struct sockaddr_in hctl;
  1215.         FILE *in;
  1216.         FILE *out;
  1217.         int tpe;
  1218.         int cpnd;
  1219.         int sunqe;
  1220.         int runqe;
  1221.         int mcse;
  1222.         int ntflg;
  1223.         char nti[17];
  1224.         char nto[17];
  1225.         int mapflg;
  1226.         char mi[MAXPATHLEN];
  1227.         char mo[MAXPATHLEN];
  1228.         } proxstruct, tmpstruct;
  1229.     struct comvars *ip, *op;
  1230.  
  1231.     abrtflag = 0;
  1232.     oldintr = signal(SIGINT, psabort);
  1233.     if (flag) {
  1234.         if (proxy)
  1235.             return;
  1236.         ip = &tmpstruct;
  1237.         op = &proxstruct;
  1238.         proxy++;
  1239.     }
  1240.     else {
  1241.         if (!proxy)
  1242.             return;
  1243.         ip = &proxstruct;
  1244.         op = &tmpstruct;
  1245.         proxy = 0;
  1246.     }
  1247.     ip->connect = connected;
  1248.     connected = op->connect;
  1249.     if (hostname) {
  1250.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1251.         ip->name[strlen(ip->name)] = '\0';
  1252.     } else
  1253.         ip->name[0] = 0;
  1254.     hostname = op->name;
  1255.     ip->hctl = hisctladdr;
  1256.     hisctladdr = op->hctl;
  1257.     ip->mctl = myctladdr;
  1258.     myctladdr = op->mctl;
  1259.     ip->in = cin;
  1260.     cin = op->in;
  1261.     ip->out = cout;
  1262.     cout = op->out;
  1263.     ip->tpe = type;
  1264.     type = op->tpe;
  1265.     if (!type)
  1266.         type = 1;
  1267.     ip->cpnd = cpend;
  1268.     cpend = op->cpnd;
  1269.     ip->sunqe = sunique;
  1270.     sunique = op->sunqe;
  1271.     ip->runqe = runique;
  1272.     runique = op->runqe;
  1273.     ip->mcse = mcase;
  1274.     mcase = op->mcse;
  1275.     ip->ntflg = ntflag;
  1276.     ntflag = op->ntflg;
  1277.     (void) strncpy(ip->nti, ntin, 16);
  1278.     (ip->nti)[strlen(ip->nti)] = '\0';
  1279.     (void) strcpy(ntin, op->nti);
  1280.     (void) strncpy(ip->nto, ntout, 16);
  1281.     (ip->nto)[strlen(ip->nto)] = '\0';
  1282.     (void) strcpy(ntout, op->nto);
  1283.     ip->mapflg = mapflag;
  1284.     mapflag = op->mapflg;
  1285.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1286.     (ip->mi)[strlen(ip->mi)] = '\0';
  1287.     (void) strcpy(mapin, op->mi);
  1288.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1289.     (ip->mo)[strlen(ip->mo)] = '\0';
  1290.     (void) strcpy(mapout, op->mo);
  1291.     (void) signal(SIGINT, oldintr);
  1292.     if (abrtflag) {
  1293.         abrtflag = 0;
  1294.         (*oldintr)();
  1295.     }
  1296. }
  1297.  
  1298. jmp_buf ptabort;
  1299. int ptabflg;
  1300.  
  1301. abortpt()
  1302. {
  1303.     printf("\n");
  1304.     (void) fflush(stdout);
  1305.     ptabflg++;
  1306.     mflag = 0;
  1307.     abrtflag = 0;
  1308.     longjmp(ptabort, 1);
  1309. }
  1310.  
  1311. proxtrans(cmd, local, remote)
  1312.     char *cmd, *local, *remote;
  1313. {
  1314.     int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
  1315.     extern jmp_buf ptabort;
  1316.     char *cmd2;
  1317.     struct fd_set mask;
  1318.  
  1319.     if (strcmp(cmd, "RETR"))
  1320.         cmd2 = "RETR";
  1321.     else
  1322.         cmd2 = runique ? "STOU" : "STOR";
  1323.     if (command("PASV") != COMPLETE) {
  1324.         printf("proxy server does not support third part transfers.\n");
  1325.         return;
  1326.     }
  1327.     tmptype = type;
  1328.     pswitch(0);
  1329.     if (!connected) {
  1330.         printf("No primary connection\n");
  1331.         pswitch(1);
  1332.         code = -1;
  1333.         return;
  1334.     }
  1335.     if (type != tmptype) {
  1336.         oldtype = type;
  1337.         switch (tmptype) {
  1338.             case TYPE_A:
  1339.                 setascii();
  1340.                 break;
  1341.             case TYPE_I:
  1342.                 setbinary();
  1343.                 break;
  1344.             case TYPE_E:
  1345.                 setebcdic();
  1346.                 break;
  1347.             case TYPE_L:
  1348.                 settenex();
  1349.                 break;
  1350.         }
  1351.     }
  1352.     if (command("PORT %s", pasv) != COMPLETE) {
  1353.         switch (oldtype) {
  1354.             case 0:
  1355.                 break;
  1356.             case TYPE_A:
  1357.                 setascii();
  1358.                 break;
  1359.             case TYPE_I:
  1360.                 setbinary();
  1361.                 break;
  1362.             case TYPE_E:
  1363.                 setebcdic();
  1364.                 break;
  1365.             case TYPE_L:
  1366.                 settenex();
  1367.                 break;
  1368.         }
  1369.         pswitch(1);
  1370.         return;
  1371.     }
  1372.     if (setjmp(ptabort))
  1373.         goto abort;
  1374.     oldintr = signal(SIGINT, abortpt);
  1375.     if (command("%s %s", cmd, remote) != PRELIM) {
  1376.         (void) signal(SIGINT, oldintr);
  1377.         switch (oldtype) {
  1378.             case 0:
  1379.                 break;
  1380.             case TYPE_A:
  1381.                 setascii();
  1382.                 break;
  1383.             case TYPE_I:
  1384.                 setbinary();
  1385.                 break;
  1386.             case TYPE_E:
  1387.                 setebcdic();
  1388.                 break;
  1389.             case TYPE_L:
  1390.                 settenex();
  1391.                 break;
  1392.         }
  1393.         pswitch(1);
  1394.         return;
  1395.     }
  1396.     sleep(2);
  1397.     pswitch(1);
  1398.     secndflag++;
  1399.     if (command("%s %s", cmd2, local) != PRELIM)
  1400.         goto abort;
  1401.     ptflag++;
  1402.     (void) getreply(0);
  1403.     pswitch(0);
  1404.     (void) getreply(0);
  1405.     (void) signal(SIGINT, oldintr);
  1406.     switch (oldtype) {
  1407.         case 0:
  1408.             break;
  1409.         case TYPE_A:
  1410.             setascii();
  1411.             break;
  1412.         case TYPE_I:
  1413.             setbinary();
  1414.             break;
  1415.         case TYPE_E:
  1416.             setebcdic();
  1417.             break;
  1418.         case TYPE_L:
  1419.             settenex();
  1420.             break;
  1421.     }
  1422.     pswitch(1);
  1423.     ptflag = 0;
  1424.     printf("local: %s remote: %s\n", local, remote);
  1425.     return;
  1426. abort:
  1427.     (void) signal(SIGINT, SIG_IGN);
  1428.     ptflag = 0;
  1429.     if (strcmp(cmd, "RETR") && !proxy)
  1430.         pswitch(1);
  1431.     else if (!strcmp(cmd, "RETR") && proxy)
  1432.         pswitch(0);
  1433.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1434.         if (command("%s %s", cmd2, local) != PRELIM) {
  1435.             pswitch(0);
  1436.             switch (oldtype) {
  1437.                 case 0:
  1438.                     break;
  1439.                 case TYPE_A:
  1440.                     setascii();
  1441.                     break;
  1442.                 case TYPE_I:
  1443.                     setbinary();
  1444.                     break;
  1445.                 case TYPE_E:
  1446.                     setebcdic();
  1447.                     break;
  1448.                 case TYPE_L:
  1449.                     settenex();
  1450.                     break;
  1451.             }
  1452.             if (cpend) {
  1453.                 char msg[2];
  1454.  
  1455.                 fprintf(cout,"%c%c",IAC,IP);
  1456.                 (void) fflush(cout); 
  1457.                 *msg = IAC;
  1458.                 *(msg+1) = DM;
  1459.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1460.                     perror("abort");
  1461.                 fprintf(cout,"ABOR\r\n");
  1462.                 (void) fflush(cout);
  1463.                 FD_ZERO(&mask);
  1464.                 FD_SET(fileno(cin), &mask);
  1465.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1466.                     if (nfnd < 0) {
  1467.                         perror("abort");
  1468.                     }
  1469.                     if (ptabflg)
  1470.                         code = -1;
  1471.                     lostpeer();
  1472.                 }
  1473.                 (void) getreply(0);
  1474.                 (void) getreply(0);
  1475.             }
  1476.         }
  1477.         pswitch(1);
  1478.         if (ptabflg)
  1479.             code = -1;
  1480.         (void) signal(SIGINT, oldintr);
  1481.         return;
  1482.     }
  1483.     if (cpend) {
  1484.         char msg[2];
  1485.  
  1486.         fprintf(cout,"%c%c",IAC,IP);
  1487.         (void) fflush(cout); 
  1488.         *msg = IAC;
  1489.         *(msg+1) = DM;
  1490.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1491.             perror("abort");
  1492.         fprintf(cout,"ABOR\r\n");
  1493.         (void) fflush(cout);
  1494.         FD_ZERO(&mask);
  1495.         FD_SET(fileno(cin), &mask);
  1496.         if ((nfnd = empty(&mask,10)) <= 0) {
  1497.             if (nfnd < 0) {
  1498.                 perror("abort");
  1499.             }
  1500.             if (ptabflg)
  1501.                 code = -1;
  1502.             lostpeer();
  1503.         }
  1504.         (void) getreply(0);
  1505.         (void) getreply(0);
  1506.     }
  1507.     pswitch(!proxy);
  1508.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1509.         if (command("%s %s", cmd2, local) != PRELIM) {
  1510.             pswitch(0);
  1511.             switch (oldtype) {
  1512.                 case 0:
  1513.                     break;
  1514.                 case TYPE_A:
  1515.                     setascii();
  1516.                     break;
  1517.                 case TYPE_I:
  1518.                     setbinary();
  1519.                     break;
  1520.                 case TYPE_E:
  1521.                     setebcdic();
  1522.                     break;
  1523.                 case TYPE_L:
  1524.                     settenex();
  1525.                     break;
  1526.             }
  1527.             if (cpend) {
  1528.                 char msg[2];
  1529.  
  1530.                 fprintf(cout,"%c%c",IAC,IP);
  1531.                 (void) fflush(cout); 
  1532.                 *msg = IAC;
  1533.                 *(msg+1) = DM;
  1534.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1535.                     perror("abort");
  1536.                 fprintf(cout,"ABOR\r\n");
  1537.                 (void) fflush(cout);
  1538.                 FD_ZERO(&mask);
  1539.                 FD_SET(fileno(cin), &mask);
  1540.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1541.                     if (nfnd < 0) {
  1542.                         perror("abort");
  1543.                     }
  1544.                     if (ptabflg)
  1545.                         code = -1;
  1546.                     lostpeer();
  1547.                 }
  1548.                 (void) getreply(0);
  1549.                 (void) getreply(0);
  1550.             }
  1551.             pswitch(1);
  1552.             if (ptabflg)
  1553.                 code = -1;
  1554.             (void) signal(SIGINT, oldintr);
  1555.             return;
  1556.         }
  1557.     }
  1558.     if (cpend) {
  1559.         char msg[2];
  1560.  
  1561.         fprintf(cout,"%c%c",IAC,IP);
  1562.         (void) fflush(cout); 
  1563.         *msg = IAC;
  1564.         *(msg+1) = DM;
  1565.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1566.             perror("abort");
  1567.         fprintf(cout,"ABOR\r\n");
  1568.         (void) fflush(cout);
  1569.         FD_ZERO(&mask);
  1570.         FD_SET(fileno(cin), &mask);
  1571.         if ((nfnd = empty(&mask,10)) <= 0) {
  1572.             if (nfnd < 0) {
  1573.                 perror("abort");
  1574.             }
  1575.             if (ptabflg)
  1576.                 code = -1;
  1577.             lostpeer();
  1578.         }
  1579.         (void) getreply(0);
  1580.         (void) getreply(0);
  1581.     }
  1582.     pswitch(!proxy);
  1583.     if (cpend) {
  1584.         FD_ZERO(&mask);
  1585.         FD_SET(fileno(cin), &mask);
  1586.         if ((nfnd = empty(&mask,10)) <= 0) {
  1587.             if (nfnd < 0) {
  1588.                 perror("abort");
  1589.             }
  1590.             if (ptabflg)
  1591.                 code = -1;
  1592.             lostpeer();
  1593.         }
  1594.         (void) getreply(0);
  1595.         (void) getreply(0);
  1596.     }
  1597.     if (proxy)
  1598.         pswitch(0);
  1599.     switch (oldtype) {
  1600.         case 0:
  1601.             break;
  1602.         case TYPE_A:
  1603.             setascii();
  1604.             break;
  1605.         case TYPE_I:
  1606.             setbinary();
  1607.             break;
  1608.         case TYPE_E:
  1609.             setebcdic();
  1610.             break;
  1611.         case TYPE_L:
  1612.             settenex();
  1613.             break;
  1614.     }
  1615.     pswitch(1);
  1616.     if (ptabflg)
  1617.         code = -1;
  1618.     (void) signal(SIGINT, oldintr);
  1619. }
  1620.  
  1621. reset()
  1622. {
  1623.     struct fd_set mask;
  1624.     int nfnd = 1;
  1625.  
  1626.     FD_ZERO(&mask);
  1627.     while (nfnd > 0) {
  1628.         FD_SET(fileno(cin), &mask);
  1629.         if ((nfnd = empty(&mask,0)) < 0) {
  1630.             perror("reset");
  1631.             code = -1;
  1632.             lostpeer();
  1633.         }
  1634.         else if (nfnd) {
  1635.             (void) getreply(0);
  1636.         }
  1637.     }
  1638. }
  1639.  
  1640. char *
  1641. gunique(local)
  1642.     char *local;
  1643. {
  1644.     static char new[MAXPATHLEN];
  1645.     char *cp = rindex(local, '/');
  1646.     int d, count=0;
  1647.     char ext = '1';
  1648.  
  1649.     if (cp)
  1650.         *cp = '\0';
  1651.     d = access(cp ? local : ".", 2);
  1652.     if (cp)
  1653.         *cp = '/';
  1654.     if (d < 0) {
  1655.         perror(local);
  1656.         return((char *) 0);
  1657.     }
  1658.     (void) strcpy(new, local);
  1659.     cp = new + strlen(new);
  1660.     *cp++ = '.';
  1661.     while (!d) {
  1662.         if (++count == 100) {
  1663.             printf("runique: can't find unique file name.\n");
  1664.             return((char *) 0);
  1665.         }
  1666.         *cp++ = ext;
  1667.         *cp = '\0';
  1668.         if (ext == '9')
  1669.             ext = '0';
  1670.         else
  1671.             ext++;
  1672.         if ((d = access(new, 0)) < 0)
  1673.             break;
  1674.         if (ext != '0')
  1675.             cp--;
  1676.         else if (*(cp - 2) == '.')
  1677.             *(cp - 1) = '1';
  1678.         else {
  1679.             *(cp - 2) = *(cp - 2) + 1;
  1680.             cp--;
  1681.         }
  1682.     }
  1683.     return(new);
  1684. }
  1685. @
  1686.  
  1687.  
  1688. 1.3
  1689. log
  1690. @New revision.
  1691. @
  1692. text
  1693. @d39 1
  1694. d232 3
  1695. a234 1
  1696. command(fmt, args)
  1697. d236 1
  1698. a236 1
  1699. {
  1700. d239 3
  1701. d245 1
  1702. a245 1
  1703.         _doprnt(fmt, &args, stdout);
  1704. d255 1
  1705. a255 1
  1706.     _doprnt(fmt, &args, cout);
  1707. @
  1708.  
  1709.  
  1710. 1.2
  1711. log
  1712. @Use vfprintf instead of _doprnt.
  1713. @
  1714. text
  1715. @d2 1
  1716. a2 1
  1717.  * Copyright (c) 1985 Regents of the University of California.
  1718. d6 10
  1719. a15 5
  1720.  * provided that this notice is preserved and that due credit is given
  1721.  * to the University of California at Berkeley. The name of the University
  1722.  * may not be used to endorse or promote products derived from this
  1723.  * software without specific prior written permission. This software
  1724.  * is provided ``as is'' without express or implied warranty.
  1725. d19 1
  1726. a19 1
  1727. static char sccsid[] = "@@(#)ftp.c    5.18 (Berkeley) 3/23/88";
  1728. d22 1
  1729. a22 2
  1730. #include "ftp_var.h"
  1731.  
  1732. d27 1
  1733. a27 1
  1734. #include <sys/param.h>
  1735. d39 2
  1736. a40 1
  1737. #include <varargs.h>
  1738. d50 1
  1739. d68 2
  1740. a69 3
  1741.         (void) strcpy(hostnamebuf, host);
  1742.     }
  1743.     else {
  1744. d72 2
  1745. a73 1
  1746.             printf("%s: unknown host\n", host);
  1747. d80 1
  1748. a80 1
  1749.         (void) strcpy(hostnamebuf, hp->h_name);
  1750. d164 1
  1751. a164 1
  1752.     char *user, *pass, *acct, *getlogin(), *mygetpass();
  1753. a168 1
  1754.         disconnect();
  1755. d192 1
  1756. a192 1
  1757.             pass = mygetpass("Password:");
  1758. d197 1
  1759. a197 1
  1760.         acct = mygetpass("Account:");
  1761. d231 2
  1762. a232 3
  1763. command(va_alist)
  1764.     va_dcl        /* Format string followed by zero or more
  1765.              * additional arguments. */
  1766. a233 2
  1767.     char *fmt;
  1768.     va_list args;
  1769. a235 2
  1770.     va_start(args);
  1771.     fmt = va_arg(args, char *);
  1772. d239 1
  1773. a239 1
  1774.         (void) vfprintf(stdout, fmt, args);
  1775. d249 1
  1776. a249 1
  1777.     (void) vfprintf(cout, fmt, args);
  1778. d260 2
  1779. d269 1
  1780. d274 1
  1781. d284 1
  1782. a284 1
  1783.                     fprintf(cout, "%c%c%c",IAC,WONT,c);
  1784. d290 1
  1785. a290 1
  1786.                     fprintf(cout, "%c%c%c",IAC,DONT,c);
  1787. d341 1
  1788. d352 1
  1789. d387 3
  1790. a389 1
  1791. sendrequest(cmd, local, remote)
  1792. d391 1
  1793. d393 2
  1794. a394 2
  1795.     FILE *fin, *dout = 0, *mypopen();
  1796.     int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)();
  1797. d396 2
  1798. a397 2
  1799.     char buf[BUFSIZ];
  1800.     long bytes = 0, hashbytes = sizeof (buf);
  1801. d401 1
  1802. d403 6
  1803. d416 1
  1804. d437 1
  1805. a437 1
  1806.         fin = mypopen(local + 1, "r");
  1807. d445 1
  1808. a445 1
  1809.         closefunc = mypclose;
  1810. d459 1
  1811. d469 2
  1812. d475 20
  1813. d500 2
  1814. d509 2
  1815. d513 1
  1816. a513 1
  1817.     dout = dataconn("w");
  1818. d517 1
  1819. d523 1
  1820. a523 3
  1821.         while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
  1822.             if ((d = write(fileno (dout), buf, c)) < 0)
  1823.                 break;
  1824. d525 3
  1825. d529 4
  1826. a532 1
  1827.                 (void) putchar('#');
  1828. d537 2
  1829. d544 7
  1830. a550 2
  1831.         if (d < 0)
  1832.             perror("netout");
  1833. d559 1
  1834. a559 1
  1835.                     hashbytes += sizeof (buf);
  1836. d581 5
  1837. a585 2
  1838.         if (ferror(dout))
  1839.             perror("netout");
  1840. d594 4
  1841. a597 2
  1842.     if (bytes > 0 && verbose)
  1843.         ptransfer("sent", bytes, &start, &stop, local, remote);
  1844. d618 2
  1845. a619 2
  1846.     if (bytes > 0 && verbose)
  1847.         ptransfer("sent", bytes, &start, &stop, local, remote);
  1848. d634 1
  1849. a634 1
  1850. recvrequest(cmd, local, remote, mode)
  1851. d637 7
  1852. a643 5
  1853.     FILE *fout, *din = 0, *mypopen();
  1854.     int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 
  1855.     int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd;
  1856.     char buf[BUFSIZ], *gunique(), msg;
  1857.     long bytes = 0, hashbytes = sizeof (buf);
  1858. d647 2
  1859. d650 8
  1860. a657 1
  1861.     if (proxy && strcmp(cmd,"RETR") == 0) {
  1862. d664 1
  1863. a664 1
  1864.     tcrflag = !crflag && !strcmp(cmd, "RETR");
  1865. d701 1
  1866. a701 1
  1867.                 chmod(local,0600) < 0) {
  1868. d727 12
  1869. a738 7
  1870.     if (strcmp(cmd, "RETR") && type != TYPE_A) {
  1871.         oldtype = type;
  1872.         oldverbose = verbose;
  1873.         if (!debug)
  1874.             verbose = 0;
  1875.         setascii();
  1876.         verbose = oldverbose;
  1877. d790 1
  1878. a790 1
  1879.         fout = mypopen(local + 1, "w");
  1880. d795 2
  1881. a796 3
  1882.         closefunc = mypclose;
  1883.     }
  1884.     else {
  1885. d804 13
  1886. d822 7
  1887. d830 2
  1888. a831 2
  1889.         while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
  1890.             if ((d = write(fileno(fout), buf, c)) < 0)
  1891. d835 4
  1892. a838 1
  1893.                 (void) putchar('#');
  1894. d843 2
  1895. d848 11
  1896. a858 4
  1897.         if (c < 0)
  1898.             perror("netin");
  1899.         if (d < 0)
  1900.             perror(local);
  1901. d862 21
  1902. d888 1
  1903. a888 1
  1904.                     hashbytes += sizeof (buf);
  1905. d892 9
  1906. a900 3
  1907.                     if (ferror (fout))
  1908.                         break;
  1909.                     (void) putc ('\r', fout);
  1910. a901 4
  1911.                 /*if (c == '\0') {
  1912.                     bytes++;
  1913.                     continue;
  1914.                 }*/
  1915. d903 1
  1916. a903 1
  1917.             (void) putc (c, fout);
  1918. d905 1
  1919. d907 1
  1920. d914 7
  1921. a920 4
  1922.         if (ferror (din))
  1923.             perror ("netin");
  1924.         if (ferror (fout))
  1925.             perror (local);
  1926. d931 2
  1927. a932 2
  1928.     if (bytes > 0 && verbose)
  1929.         ptransfer("received", bytes, &start, &stop, local, remote);
  1930. d1003 1
  1931. a1003 1
  1932.         while ((c = read(fileno(din), buf, sizeof (buf))) > 0)
  1933. d1023 2
  1934. a1024 2
  1935.     if (bytes > 0 && verbose)
  1936.         ptransfer("received", bytes, &start, &stop, local, remote);
  1937. d1116 2
  1938. a1117 2
  1939. ptransfer(direction, bytes, t0, t1, local, remote)
  1940.     char *direction, *local, *remote;
  1941. d1124 3
  1942. a1126 2
  1943.     tvsub(&td, t1, t0);
  1944.     s = td.tv_sec + (td.tv_usec / 1000000.);
  1945. d1128 4
  1946. a1131 7
  1947.     bs = bytes / nz(s);
  1948.     if (local && *local != '-')
  1949.         printf("local: %s ", local);
  1950.     if (remote)
  1951.         printf("remote: %s\n", remote);
  1952.     printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
  1953.         bytes, direction, s, bs / 1024.);
  1954. @
  1955.  
  1956.  
  1957. 1.1
  1958. log
  1959. @Initial revision
  1960. @
  1961. text
  1962. @d35 1
  1963. d226 4
  1964. a229 1
  1965. command(fmt, args)
  1966. d231 1
  1967. a231 1
  1968. {
  1969. d234 2
  1970. d239 1
  1971. a239 1
  1972.         _doprnt(fmt, &args, stdout);
  1973. d249 1
  1974. a249 1
  1975.     _doprnt(fmt, &args, cout);
  1976. @
  1977.